using FutureCoreEditor;
using Spine;
using Spine.Unity;
using Spine.Unity.Editor;
using System.IO;
using UnityEditor;
using UnityEngine;

public class BuildSkeletonTool : Editor
{
    private static string SkeletonPath = "Assets/_Game/ResourcesArt/Skeleton";
    private static string DefaultAnimName = "Idle";

    [MenuItem("[FutureCore]/SkeletonObj/生成所有2D骨骼对象", false, 10)]
    private static void BuildAllSkeletonObjMenu()
    {
        DirectoryInfo raw = new DirectoryInfo(SkeletonPath);
        foreach (DirectoryInfo dictorys in raw.GetDirectories())
        {
            string path = SkeletonPath + "/" + dictorys.Name;
            BuildSpine(path);
        }
        AssetDatabase.Refresh();
        DebugUtil.Log("生成所有2D骨骼对象完成");
    }

    [MenuItem("[FutureCore]/SkeletonObj/生成选中2D骨骼对象", false, 11)]
    private static void BuildSelectSkeletonObjMenu()
    {
        Object[] pathsArr = Selection.GetFiltered(typeof(DefaultAsset), SelectionMode.Assets);
        foreach (Object obj in pathsArr)
        {
            string path = AssetDatabase.GetAssetPath(obj);
            if (string.IsNullOrEmpty(path))
            {
                DebugUtil.LogError("路径错误");
                return;
            }
            BuildSpine(path);
        }
        DebugUtil.Log("生成选中2D骨骼对象完成");
    }

    private static void BuildSpine(string path)
    {
        DirectoryInfo dictory = new DirectoryInfo(path);
        string roleName = path.Substring(path.LastIndexOf("/") + 1);
        GameObject role = new GameObject(roleName);
        //所有子文件夹
        foreach (DirectoryInfo dictoryDirections in dictory.GetDirectories())
        {
            FileInfo[] skeletonData = dictoryDirections.GetFiles("*SkeletonData.asset");
            if (skeletonData.Length == 0)
            {
                DebugUtil.LogError(roleName + "," + dictoryDirections.Name + "找不到SkeletonData");
                continue;
            }
            string assetPath = path + "/" + dictoryDirections.Name + "/" + skeletonData[0].Name;
            SkeletonDataAsset sda = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Object)) as SkeletonDataAsset;
            SkeletonAnimation skeletonAnimation = SpineEditorUtilities.InstantiateSkeletonAnimation(sda);
            Reload(skeletonAnimation);
            skeletonAnimation.AnimationName = DefaultAnimName;
            skeletonAnimation.loop = true;
            skeletonAnimation.gameObject.name = dictoryDirections.Name;
            skeletonAnimation.gameObject.transform.SetParent(role.transform);
            CheckSlot(skeletonAnimation);
            BindSlot(skeletonAnimation);
            SetShader(skeletonAnimation);
        }
        PrefabUtility.CreatePrefab(path + "/" + roleName + ".prefab", role);
        DestroyImmediate(role);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    private static void Reload(SkeletonAnimation skeletonAnimation)
    {
        SkeletonRenderer component = skeletonAnimation as SkeletonRenderer;
        if (component.skeletonDataAsset != null)
        {
            foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets)
            {
                if (aa != null) aa.Clear();
            }
            component.skeletonDataAsset.Clear();
        }
        component.Initialize(true);
    }

    private static void CheckSlot(SkeletonAnimation skeletonAnimation)
    {
        Slot hitPointSlot = skeletonAnimation.Skeleton.FindSlot(EPAnimSlotConst.HitPoint);
        Slot atkPointSlot = skeletonAnimation.Skeleton.FindSlot(EPAnimSlotConst.AtkPoint);
        Debug.AssertFormat(hitPointSlot != null, "{0}:没有找到{1}插槽", skeletonAnimation.gameObject.name, EPAnimSlotConst.HitPoint);
        Debug.AssertFormat(atkPointSlot != null, "{0}:没有找到{1}插槽", skeletonAnimation.gameObject.name, EPAnimSlotConst.AtkPoint);

        Spine.Animation idleAnim = skeletonAnimation.skeleton.Data.FindAnimation(EPFightActorAnimType.Idle.ToString());
        Spine.Animation moveAnim = skeletonAnimation.skeleton.Data.FindAnimation(EPFightActorAnimType.Move.ToString());
        Spine.Animation atkAnim = skeletonAnimation.skeleton.Data.FindAnimation(EPFightActorAnimType.Atk.ToString());
        Spine.Animation skillAnim = skeletonAnimation.skeleton.Data.FindAnimation(EPFightActorAnimType.Skill.ToString());
        Spine.Animation dizzyAnim = skeletonAnimation.skeleton.Data.FindAnimation(EPFightActorAnimType.Dizzy.ToString());
        Spine.Animation riseAnim = skeletonAnimation.skeleton.Data.FindAnimation(EPFightActorAnimType.Rise.ToString());
        Debug.AssertFormat(idleAnim != null, "{0}:缺失{1}动画", skeletonAnimation.gameObject.name, EPFightActorAnimType.Idle);
        Debug.AssertFormat(moveAnim != null, "{0}:缺失{1}动画", skeletonAnimation.gameObject.name, EPFightActorAnimType.Move);
        Debug.AssertFormat(atkAnim != null, "{0}:缺失{1}动画", skeletonAnimation.gameObject.name, EPFightActorAnimType.Atk);
        Debug.AssertFormat(skillAnim != null, "{0}:缺失{1}动画", skeletonAnimation.gameObject.name, EPFightActorAnimType.Skill);
        Debug.AssertFormat(dizzyAnim != null, "{0}:缺失{1}动画", skeletonAnimation.gameObject.name, EPFightActorAnimType.Dizzy);
        Debug.AssertFormat(riseAnim != null, "{0}:缺失{1}动画", skeletonAnimation.gameObject.name, EPFightActorAnimType.Rise);
    }

    private static void BindSlot(SkeletonAnimation skeletonAnimation)
    {
        GameObject root = new GameObject("bones");
        root.transform.SetParent(skeletonAnimation.transform, false);
        SetSlot(skeletonAnimation, EPAnimSlotConst.HitPoint, root);
        SetSlot(skeletonAnimation, EPAnimSlotConst.AtkPoint, root);
    }

    private static void SetSlot(SkeletonAnimation skeletonAnimation, string slotName, GameObject root)
    {
        GameObject point = new GameObject(slotName);
        PointFollower follower = point.AddComponent<PointFollower>();
        follower.skeletonRenderer = skeletonAnimation;
        follower.slotName = slotName;
        follower.pointAttachmentName = slotName;
        follower.followRotation = false;
        follower.followSkeletonFlip = true;
        follower.followSkeletonZPosition = false;
        point.transform.SetParent(root.transform, false);
    }

    private static void SetLayer(GameObject go)
    {
        Transform[] ts = go.GetComponentsInChildren<Transform>(false);
        foreach (Transform item in ts)
        {
            item.gameObject.layer = LayerMask.NameToLayer("Skeleton");
        }
    }

    private static void SetShader(SkeletonAnimation skeletonAnimation)
    {
        Renderer render = skeletonAnimation.GetComponent<Renderer>();
        foreach (Material m in render.sharedMaterials)
        {
            m.shader = Shader.Find("Spine/Skeleton Fill");
        }
    }
}